package org.example.domain.model.service.url;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.example.constant.RedisCacheConstant;
import org.example.domain.config.UrlShortenerConfig;
import org.example.domain.model.entity.url.UrlShortenerGroup;
import org.example.domain.model.entity.url.mapstruct.UrlShortenerGroupRespMapstruct;
import org.example.domain.model.entity.url.req.UrlShortenerGroupSortReq;
import org.example.domain.model.entity.url.req.UrlShortenerUpdateGroupReq;
import org.example.domain.model.entity.url.resp.QueryGroupByCountResp;
import org.example.domain.model.entity.url.resp.UrlShortenerGroupResp;
import org.example.domain.repository.UrlGroupDomainRepository;
import org.example.infrastructure.repository.remote.RemoteUrlShortenerRepository;
import org.example.utils.SnowFlake;
import org.example.web.exception.ServerException;
import org.example.web.result.BaseErrorCode;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

@Service
@RequiredArgsConstructor
@Slf4j
public class UrlGroupDomainService {
    private final UrlGroupDomainRepository urlGroupDomainRepository;
    private final RedissonClient redissonClient;
    private final UrlShortenerConfig urlShortenerConfig;
    private final RemoteUrlShortenerRepository remoteUrlShortenerRepository;

    public void saveGroup(String groupName, String userName) {
        RLock lock = redissonClient.getLock(RedisCacheConstant.LOCK_GROUP_CREATE_KEY + userName);
        lock.lock();
        try {
            Integer groupCount = urlGroupDomainRepository.selectCountByUserName(userName);
            if (groupCount != 0 && Objects.equals(groupCount, urlShortenerConfig.getGroup().getMaxNum())) {
                throw new ServerException(String.format("已超出最大分组数：%d", urlShortenerConfig.getGroup().getMaxNum()));
            }

            SnowFlake snowFlake = new SnowFlake();
            String gid = String.valueOf(snowFlake.nextId());
            UrlShortenerGroup urlShortenerGroup = UrlShortenerGroup.builder()
                    .gid(gid)
                    .sortOrder(groupCount)
                    .userName(userName)
                    .groupName(groupName)
                    .build();
            urlGroupDomainRepository.insertGroup(urlShortenerGroup);
        }catch (Exception e){
            log.error(e.getMessage());
            throw new ServerException(BaseErrorCode.SERVICE_ERROR);
        }finally {
            lock.unlock();
        }
    }

    public List<UrlShortenerGroupResp> listGroup(String userName) {
        List<UrlShortenerGroup> groupList = urlGroupDomainRepository.listGroupByUserName(userName);
        List<QueryGroupByCountResp> queryGroupByCountRespList = remoteUrlShortenerRepository.queryGroupByCount(groupList.stream().map(UrlShortenerGroup::getGid).toList());
        List<UrlShortenerGroupResp> urlShortenerGroupRespList = UrlShortenerGroupRespMapstruct.INSTANCE.queryGroupByCountRespListToUrlShortenerGroupRespList(queryGroupByCountRespList);
        urlShortenerGroupRespList.forEach(each -> {
            Optional<QueryGroupByCountResp> first = queryGroupByCountRespList.stream()
                    .filter(item -> Objects.equals(item.getGid(), each.getGid()))
                    .findFirst();
            first.ifPresent(item -> each.setUrlShortenerCount(first.get().getUrlShortenerCount()));
        });
        return urlShortenerGroupRespList;
    }

    public void updateGroup(UrlShortenerUpdateGroupReq req, String userName) {
        urlGroupDomainRepository.updateGroup(req.getGid(), userName, req.getGroupName());
    }

    public void deleteGroup(String gid, String userName) {
        urlGroupDomainRepository.deleteGroup(gid, userName);
    }

    public void sortGroup(List<UrlShortenerGroupSortReq> reqList, String userName) {
        urlGroupDomainRepository.sortGroup(reqList, userName);
    }

    public List<String> selectGitListByUserName(String userName) {
        return urlGroupDomainRepository.selectGitListByUserName(userName);
    }
}
